// Main file

#include "stdafx.h"
#include "VideoEncoder.h"
#include "ffmpegDecode.h"
#include <windows.h>
#include "Settings.h"

//#define FILE_IN_NAME          "http://s4.safesreview.com/video/e51c3d790162446783dcaaa91b7c6a6f4da29664/serials/Obruch/Obruch-s01e201.flv"
#define FILE_IN_NAME          "e:\\my\\test.flv"
#define OUTPUT_FILE_PREFIX "e:\\my\\image%d.bmp"
#define FRAME_COUNT        2500

bool BMPSave(const char *pFileName, AVFrame * frame, int w, int h)
{
	bool bResult = false;

	if (frame)
	{
		FILE* file = fopen(pFileName, "wb");

		if (file)
		{
      // RGB image
			int imageSizeInBytes = 3 * w * h;
			int headersSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
			int fileSize = headersSize + imageSizeInBytes;
			
			uint8_t * pData = new uint8_t[headersSize];
			
			if (pData != NULL)
			{
				BITMAPFILEHEADER& bfHeader = *((BITMAPFILEHEADER *)(pData));

				bfHeader.bfType = 'MB';
				bfHeader.bfSize = fileSize;
				bfHeader.bfOffBits = headersSize;
				bfHeader.bfReserved1 = bfHeader.bfReserved2 = 0;

				BITMAPINFOHEADER& bmiHeader = *((BITMAPINFOHEADER *)(pData + headersSize - sizeof(BITMAPINFOHEADER)));

				bmiHeader.biBitCount = 3 * 8;
				bmiHeader.biWidth    = w;
				bmiHeader.biHeight   = h;
				bmiHeader.biPlanes   = 1;
				bmiHeader.biSize     = sizeof(bmiHeader);
				bmiHeader.biCompression = BI_RGB;
				bmiHeader.biClrImportant = bmiHeader.biClrUsed = 
          bmiHeader.biSizeImage = bmiHeader.biXPelsPerMeter = 
          bmiHeader.biYPelsPerMeter = 0;
				
        fwrite(pData, headersSize, 1, file);

				uint8_t *pBits = frame->data[0] + frame->linesize[0] * h - frame->linesize[0];
				int nSpan      = - frame->linesize[0];

				int numberOfBytesToWrite = 3 * w;

				for (size_t i = 0; i < h; ++i, pBits += nSpan)	
				{
          fwrite(pBits, numberOfBytesToWrite, 1, file);
				}
				
				bResult = true;
				delete [] pData;				
			}

			fclose(file);
		}
	}

	return bResult;
}

// Create test video frame
void CreateFrame(char * buffer, int w, int h, int bytespan)
{
  int wxh = w * h;
  static float seed = 1.0;
  for (int i = 0; i < h; i ++)
  {
    char* line = buffer + i * bytespan;
    for (int j = 0; j < w; j ++)
    {
      // RGB
      line[0] = 255 * sin(((float)i / wxh * seed) * 3.14);
      line[1] = 255 * cos(((float)j / wxh * seed) * 3.14);
      line[2] = 255 * sin(((float)(i + j) / wxh * seed) * 3.14);
      line += 3;
    }
  }
  seed = seed + 2.2;
}

// Create sample
void CreateSample(short * buffer, int sampleCount)
{
  static float shift = 0.0;
  // 44100 sample rate
  float nu = 3.14 / (8000.0f) * 100.0f;
  for (int i = 0; i < sampleCount; i ++)
  {
    // Sound :)
    buffer [i] = (sin(i * nu + shift) + sin(2 * i * nu + 2 * shift))* 0x4FFF;
  }
  shift = shift + nu * sampleCount;
}

int _tmain(int argc, _TCHAR* argv[])
{
	VideoEncoder encoder;
	FFmpegDecoder decoder;

	if (decoder.OpenFile(std::string(FILE_IN_NAME)))
	{
		int w = decoder.GetWidth();
		int h = decoder.GetHeight();

		if (encoder.InitFile(std::string(FILE_NAME), std::string(CONTAINER)))
		{

			for (int i = 0; i < FRAME_COUNT; i++)
			{
				AVFrame * frame = decoder.GetNextFrame();
				if (frame)
				{
					if (!encoder.AddFrame(frame, NULL, 0))
					{
						printf("Cannot write frame\n");
					} 

					av_free(frame->data[0]);
					av_free(frame);
				}				
			}

			encoder.Finish();
		}
		else
		{
			printf ("Cannot open file " FILE_NAME "\n");
		}

		decoder.CloseFile();
	}
	else
	{
		printf ("Cannot open file " FILE_NAME "\n");
	}

  //VideoEncoder encoder;

  //if (encoder.InitFile(std::string(FILE_NAME), std::string(CONTAINER)))
  //{
  //  int w = W_VIDEO;
  //  int h = H_VIDEO;
  //  AVFrame* frame = avcodec_alloc_frame();
  //  int nSampleSize = 2 * 8000.0f / 25.0f; // 1 / 25 sec * FORMAT SIZE(S16)
  //  char* sample = new char[nSampleSize];
  //  // Create frame
  //  int bufferImgSize = avpicture_get_size(PIX_FMT_BGR24, w, h);
	 // uint8_t * buffer = (uint8_t*)av_mallocz(bufferImgSize);
	 // avpicture_fill((AVPicture*)frame, buffer, PIX_FMT_BGR24, w, h);

  //  for (int i = 0; i < FRAME_COUNT; i++)
  //  {      
  //    CreateFrame((char *)frame->data[0], w, h, frame->linesize[0]);
  //    CreateSample((short *)sample, nSampleSize / 2);
  //    if (!encoder.AddFrame(frame, sample, nSampleSize))
  //    {
  //      printf("Cannot write frame\n");
  //    } 
  //  }

  //  encoder.Finish();
  //  av_free(frame->data[0]);
  //  av_free(frame);
  //  delete[] sample;
  //  sample = NULL;
  //}
  //else
  //{
  //  printf ("Cannot open file " FILE_NAME "\n");
  //}

	return 0;
}

